package com.xc.erp.modules.erp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xc.erp.common.utils.*;
import com.xc.erp.modules.erp.domain.pojo.JshFunction;
import com.xc.erp.modules.erp.domain.vo.MetaVo;
import com.xc.erp.modules.erp.domain.vo.RouterVo;
import com.xc.erp.modules.erp.mapper.JshFunctionMapper;
import com.xc.erp.modules.erp.service.JshFunctionService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 *
 */
@Service
public class JshFunctionServiceImpl extends ServiceImpl<JshFunctionMapper, JshFunction>
    implements JshFunctionService {

    /**
     * 查询菜单列表
     * @param userId 用户编号
     * @return 菜单列表集合
     */
    @Override
    public List<JshFunction> selectMenuById(Long userId) {
        List<JshFunction> rootMenu = new ArrayList<JshFunction>();
        List<JshFunction> functionList;
        if (SecurityUtils.isAdmin(userId)){
           functionList = baseMapper.selectFunctionAll();
        } else {
            functionList = baseMapper.selectFunctionById(userId);
        }
        //获取所有的一级菜单
        for (JshFunction function : functionList) {
            //父节点0为根节点
            if("0".equals(function.getParentNumber())){
                rootMenu.add(function);
            }
        }
        //设置子菜单
        for (JshFunction function : rootMenu) {
            List<JshFunction> child = getChild(function.getNumber(),functionList);
            function.setChildren(child);
        }
        return rootMenu;
    }

    /**
     * 查询菜单子集合
     * @param number 编号
     * @param functionList 查询的菜单集合
     * @return  子菜单
     */
    private List<JshFunction> getChild(String number, List<JshFunction> functionList) {
        List<JshFunction> childList = new ArrayList<>();
        for (JshFunction function : functionList) {
            if(function.getParentNumber().equals(number)){
                childList.add(function);
            }
        }
        //递归
        for (JshFunction function : childList) {
            function.setChildren(getChild(function.getNumber(),functionList));
        }
        if(childList.size() == 0){
            return new ArrayList<JshFunction>();
        }
        return childList;
    }

    /**
     * 构建前端路由所需要的菜单
     *
     * @param functionList 菜单列表
     * @return 路由列表
     */
    @Override
    public List<RouterVo> buildMenus(List<JshFunction> functionList) {
        List<RouterVo> routers = new LinkedList<RouterVo>();
        for (JshFunction function : functionList)
        {
            RouterVo router = new RouterVo();
            router.setId(function.getId());
            router.setHidden("1".equals("0"));
            router.setName(getRouteName(function));
            router.setPath(getRouterPath(function));
            router.setComponent(getComponent(function));
            router.setQuery("");
            router.setMenuName(function.getName());
            router.setMeta(new MetaVo(function.getName(), function.getIcon(), StringUtils.equals("1", "0"), function.getUrl()));
            List<JshFunction> cMenus = function.getChildren();
            if (cMenus != null && !cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(function.getMenuType()))
            {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(buildMenus(cMenus));
            }
            else if (isMenuFrame(function))
            {
                router.setId(function.getId());
                router.setMeta(null);
                router.setMenuName(function.getName());
                List<RouterVo> childrenList = new ArrayList<RouterVo>();
                RouterVo children = new RouterVo();
                children.setPath(function.getUrl());
                children.setComponent(function.getComponent());
                children.setName(StringUtils.capitalize(function.getUrl()));
                children.setMeta(new MetaVo(function.getName(), function.getIcon(), StringUtils.equals("1", "1"), function.getUrl()));
                children.setQuery("");
                childrenList.add(children);
                router.setChildren(childrenList);
            }
            else if ("0".equals(function.getParentNumber()) && isInnerLink(function))
            {
                router.setId(function.getId());
                router.setMenuName(function.getName());
                router.setMeta(new MetaVo(function.getName(), function.getIcon()));
                router.setPath("/");
                List<RouterVo> childrenList = new ArrayList<RouterVo>();
                RouterVo children = new RouterVo();
                String routerPath = innerLinkReplaceEach(function.getUrl());
                children.setPath(routerPath);
                children.setComponent(UserConstants.INNER_LINK);
                children.setName(StringUtils.capitalize(routerPath));
                children.setMeta(new MetaVo(function.getName(), function.getIcon(), function.getUrl()));
                childrenList.add(children);
                router.setChildren(childrenList);
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 获取路由名称
     *
     * @param function 菜单信息
     * @return 路由名称
     */
    public String getRouteName(JshFunction function)
    {
        String routerName = StringUtils.capitalize(function.getUrl());
        // 非外链并且是一级目录（类型为目录）
        if (isMenuFrame(function))
        {
            routerName = StringUtils.EMPTY;
        }
        return routerName;
    }

    /**
     * 获取路由地址
     *
     * @param function 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(JshFunction function)
    {
        String routerPath = function.getUrl();
        // 内链打开外网方式
        if (!function.getParentNumber().equals("0") && isInnerLink(function))
        {
            routerPath = innerLinkReplaceEach(routerPath);
        }
        // 非外链并且是一级目录（类型为目录）
        if (function.getParentNumber().equals("0") && UserConstants.TYPE_DIR.equals(function.getMenuType())
                && UserConstants.NO_FRAME.equals("1"))
        {
            routerPath = "/" + function.getUrl();
        }
        // 非外链并且是一级目录（类型为菜单）
        else if (isMenuFrame(function))
        {
            routerPath = "/";
        }
        return routerPath;
    }

    /**
     * 获取组件信息
     *
     * @param menu 菜单信息
     * @return 组件信息
     */
    public String getComponent(JshFunction menu)
    {
        String component = UserConstants.LAYOUT;
        if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu))
        {
            component = menu.getComponent();
        }
        else if (StringUtils.isEmpty(menu.getComponent()) && !"0".equals(menu.getParentNumber()) && isInnerLink(menu))
        {
            component = UserConstants.INNER_LINK;
        }
        else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
        {
            component = UserConstants.PARENT_VIEW;
        }
        return component;
    }

    /**
     * 是否为菜单内部跳转
     *
     * @param function 菜单信息
     * @return 结果
     */
    public boolean isMenuFrame(JshFunction function)
    {
        return "0".equals(function.getParentNumber()) && UserConstants.TYPE_MENU.equals(function.getMenuType())
                && "1".equals(UserConstants.NO_FRAME);
    }

    /**
     * 是否为内链组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    public boolean isInnerLink(JshFunction menu)
    {
        return "1".equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getUrl());
    }

    /**
     * 是否为parent_view组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    public boolean isParentView(JshFunction menu)
    {
        return !"0".equals(menu.getParentNumber()) && UserConstants.TYPE_DIR.equals(menu.getMenuType());
    }

    /**
     * 内链域名特殊字符替换
     *
     * @return
     */
    public String innerLinkReplaceEach(String path)
    {
        return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, "." },
                new String[] { "", "", "", "/" });
    }

    @Override
    public Page<JshFunction> list(Integer pageSize, Integer pageNum, String name) {
        Page<JshFunction> page=new Page<>(pageSize,pageNum);
        QueryWrapper<JshFunction> queryWrapper=new QueryWrapper<JshFunction>();
        if (!StringUtils.isEmpty(name)){
            queryWrapper.like("name",name);
        }
        Page<JshFunction> jshFunctionPage = this.baseMapper.selectPage(page, queryWrapper);
        return jshFunctionPage;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void batchSetStatus(boolean status, Long[] ids) {
        List<JshFunction> functionList = new ArrayList<>();
        for (int i = 0; i < ids.length; i++) {
            JshFunction function = new JshFunction();
            function.setEnabled(status);
            function.setId(ids[i]);
            functionList.add(function);
        }
        this.updateBatchById(functionList);
    }

    @Override
    public boolean checkIsNumberExist(Long id, String number) {
        QueryWrapper<JshFunction> queryWrapper=new QueryWrapper<>();
        if (!StringUtils.isEmpty(number)){
            queryWrapper.eq("number",number);
        }
        JshFunction jshFunction = this.baseMapper.selectOne(queryWrapper);

        if (jshFunction!=null){
            if (id!=null){
                if (id.equals(jshFunction.getId())){
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    @Override
    public List<JshFunction> listFunction() {
        QueryWrapper<JshFunction> wrapper = new QueryWrapper<>();
        wrapper.in("menu_type","M","C");
        return returnMenu(this.list(wrapper));
    }

    /**
     * 查询角色拥有的权限
     * @param roleId 角色编号
     * @return 权限列表
     */
    @Override
    public List<JshFunction> selectFunctionRole(Integer roleId) {
        List<JshFunction> functionList = baseMapper.selectFunctionByRoleId(roleId);
        return returnMenu(functionList);
    }

    @Override
    public boolean checkIsNameExist(Long id,String name) {
        QueryWrapper<JshFunction> queryWrapper=new QueryWrapper<>();
        if (!StringUtils.isEmpty(name)){
            queryWrapper.eq("name",name);
        }
        JshFunction jshFunction = this.baseMapper.selectOne(queryWrapper);

        if (jshFunction!=null){
            if (id!=null){
                if (id.equals(jshFunction.getId())){
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    private List<JshFunction> returnMenu(List<JshFunction> list){
        //存储需要删除的元素
        ArrayList<JshFunction> remove = new ArrayList<>();
        for (JshFunction function : list) {
            ArrayList<JshFunction> children = new ArrayList<>();
            for (JshFunction jshFunction : list) {
                //判断有没有子菜单
                if (String.valueOf(function.getNumber()).equals(String.valueOf(jshFunction.getParentNumber()))) {
                    //添加到子菜单
                    children.add(jshFunction);
                    //有子菜单删除
                    remove.add(jshFunction);
                }
            }
            //子菜单添加没有就添加null
            if (children.size() == 0) {
                function.setChildren(null);
            }
            else {
                function.setChildren(children);
            }
        }
        // 删除list中为子菜单中的元素
        for (JshFunction function : remove) {
            list.remove(function);
        }
        return list;
    }
}




